<template>
	<view>
		<!-- use-chat-record-mode：开启聊天记录模式 -->
		<!-- use-virtual-list：开启虚拟列表模式 -->
		<!-- cell-height-mode：设置虚拟列表模式高度不固定 -->
		<!-- safe-area-inset-bottom：开启底部安全区域适配 -->
		<!-- bottom-bg-color：设置slot="bottom"容器的背景色，这里设置为和chat-input-bar的背景色一致 -->
		<z-paging ref="paging" v-model="talkList" use-chat-record-mode use-virtual-list cell-height-mode="dynamic" safe-area-inset-bottom bottom-bg-color="#f8f8f8"

				  @query="getHistoryMsg" @keyboardHeightChange="keyboardHeightChange" @hidedKeyboard="hidedKeyboard">

			<!-- style="transform: scaleY(-1)"必须写，否则会导致列表倒置！！！ -->
			<!-- 注意不要直接在chat-item组件标签上设置style，因为在微信小程序中是无效的，请包一层view -->
			<template #cell="{item,index}">
				<view style="transform: scaleY(-1)">
				    <chat-item :item="item"></chat-item>
				</view>
			</template>

			<!-- 底部聊天输入框 -->
			<template #bottom>
				<chat-input-bar ref="inputBar" @send="send" @handleOpen="handleopen" :isSearch="search_url!=''?true:false"/>
			</template>
		</z-paging>

		<!--<user-model ref="userModel" :chatIntegral="chatIntegral" @save="updateUserInfo"></user-model>-->
		<setup-model ref="userModel" :host="baseUrl" :model="baseModel" @save="updateSetup"></setup-model>
		<u-top-tips ref="uTips"></u-top-tips>
	</view>
</template>

<script>
	const globalData = getApp().globalData;

	import config from '@/global/config.js';
	import chatInputBar from '@/components/chat-input-bar/chat-input-bar.vue'
	import chatItem from '@/components/chat-item/chat-item.vue'
    function truncateContent(text, maxLength = 100) {
        return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
    }
	export default {
		components:{chatInputBar,chatItem},
		data() {
			return {
				// 签到
				isSign: false,
				signShow: false,
				signTitle: '',
				signIntegral: 0,
				inviteIntegral: 0,
				adIntegral: 0,
				chatIntegral: 0,
				// 登录弹窗
				loginShow: false,
				talkList: [],
				content: '',
				downShow: false,
				downTitle: '',
				show: false,
                messages:[],
                
                search_url:config.search_url,
                proxyUrl:'',
                baseUrl:'',
                baseModel:'',
                SendingType:'chat',
                requesttype:1,
                

				socketState:false,
				sendState:false,
				isTyping:false,
				currentMassage:{},
				currentIndex:0,
				currentContent:'',
				typingInterval:50,
				userInfo:null,
				imitateIndex:0
			}
		},
		onLoad(options) {
			//this.userInfo = this.getLoginUserInfo();
            this.init();
		},
		methods: {
		    init(){
                  if(config.proxy_url)this.proxyUrl = config.proxy_url;
                  if(config.default_type)this.requesttype = config.default_type;
                  var carchurl =uni.getStorageSync('cache_baseUrl');
                  if(carchurl)this.baseUrl =carchurl;
                  else if(config.default_url)this.baseUrl =config.default_url;
                  var carchmodel =uni.getStorageSync('cache_baseModel');
                  if(carchmodel)this.baseModel =carchmodel;
                  else if(config.default_model)this.baseModel = config.default_model;
		    },
			updateSetup(e){//console.log(e);
			     if(e.host){
			         uni.setStorageSync('cache_baseUrl',e.host);
                     this.baseUrl =e.host;
			     }
			     if(e.model){
			         uni.setStorageSync('cache_baseModel',e.model);
                     this.baseModel =e.model;
			     }
			},
			// 获取历史消息
			getHistoryMsg() {
				let get = async () => {
					let data = [{
						content: globalData.appName+"为您服务，可以问我一些问题，您的问题描述越完整的，我的回答越精确！", // 消息内容
						type: 0,// 此为消息类别，设 1 为发出去的消息，0 为收到对方的消息,
						state: 0,
						icon:'/static/logo.png',
						end:true
					}];
					this.$refs.paging.complete(data);
				}
				get();
			},
			// 监听键盘高度改变，请不要直接通过uni.onKeyboardHeightChange监听，否则可能导致z-paging内置的键盘高度改变监听失效（如果不需要切换表情面板则不用写）
			keyboardHeightChange(res) {
				this.$refs.inputBar.updateKeyboardHeightChange(res);
			},
			// 用户尝试隐藏键盘，此时如果表情面板在展示中，应当通知chatInputBar隐藏表情面板（如果不需要切换表情面板则不用写）
			hidedKeyboard() {
				this.$refs.inputBar.hidedKeyboard();
			},
			startTyping() {
				if (this.isTyping) return;
				var that = this;
				this.isTyping = true;
				setTimeout(() => {
					if (this.currentIndex <= this.currentContent.length) {
						that.talkList[0].state = 1;
						that.talkList[0].content = this.currentContent.substring(0, this.currentIndex++);
						that.$forceUpdate()
						// 设置当前滚动的位置
						//that.setPageScrollTo();
						this.isTyping = false;
						this.startTyping();
					} else {
						if(that.$data.currentMassage.done){
							that.talkList[0].end = true;
							that.$data.currentIndex = 0;
							that.$data.currentContent = '';
							that.$data.sendState = false;
						}
						this.isTyping = false;
					}
				}, this.typingInterval);
			},
			handleopen() {
				this.$refs.userModel.open('base');
			},
			send(data){
			 
				var that = this;
				that.content = data.msg;
				if (!that.content) {
					that.$refs.uTips.show({title: '请输入有效的内容',type: 'error',duration: '2300'});
					return false;
				}
				// 添加锁，避免重复发送
				if(this.$data.sendState){
					return false;
				}
				that.$data.sendState = true;
				that.$refs.inputBar.setMsg('');
				// 向聊天面板添加一条我发送的消息
				that.talkList.unshift({
					content: that.content, // 消息内容
					type: 1 ,// 此为消息类别，设 1 为发出去的消息，0 为收到对方的消息,
					end:true, // 是否完毕
					icon:(this.userInfo&&this.userInfo.icon?this.userInfo.icon:'/static/avatar.png'),
				})
				that.talkList.unshift({
					content: '', // 消息内容
                    searchlist:'',
					type: 0 ,// 此为消息类别，设 1 为发出去的消息，0 为收到对方的消息,
					end:false, // 是否完毕，当消息为对方发送的消息时，如果未完毕则显示对方流式相应光标
					icon:'/static/logo.png',
				})
                if(data.is_net){
                    that.netsend(data.msg);
                }else{
                    that.nonetsend(data.msg);
                }
			},
			netsend(msg){
				var that = this;
                var data={'q':msg};
                var url = that.search_url+msg;
			    uni.request({
                  url: url,
                  method: 'GET',
                  success: (res) => {
                    console.log('请求成功：', res);
                    if(res.statusCode==200 && res.data && res.data.status==1 && res.data.list && res.data.list.results){
                        var searchstr= '';
                        
                        res.data.list.results.forEach((result, index) => {
                            searchstr += `\n[来源${index + 1}] ${result.title || '无标题'}\n` +
                                                  `${truncateContent(result.content || '')}\n` +
                                                  `URL: ${result.url || '无链接'}`;
                        });
                        if(searchstr)searchstr += '\n\n回答时请引用来源编号如[1][2]。';
                        if(searchstr){
                            that.talkList[0].searchlist = res.data.list.results;
                            // 添加助手消息
                            const systemMessage = {
                                role: 'system',
                                content: '你是一个智能助手，回答要简洁专业。可以使用网络搜索结果增强回答。\n\n当前网络搜索结果:'+searchstr,
                                isPending: true,
                                timestamp: Date.now()
                            };
                            that.messages.push(systemMessage);
                            const userMessage= { role: 'user', content: msg, timestamp: Date.now() }
                            that.messages.push(userMessage);
				            that.$forceUpdate()

            				// 回复消息归0，从第一条开始，现实流式响应也是一段一段的收到消息并且进行响应
            				that.imitateIndex = 0;
                            that.toSend(msg);
                            return;    
                        }                
                    }
                    that.nonetsend(msg);
                  },
                  fail: (err) => {
                    console.error('请求失败：', err);
                    that.nonetsend(msg);
                  }
                });
			},
			nonetsend(msg){
				var that = this;
                that.messages.push({
    				role: "user",
    				content: msg,
                    timestamp: Date.now()
    			});
                // 添加助手消息（初始为空）
                const assistantMessage = {
                    role: 'assistant',
                    content: '',
                    isPending: true,
                    timestamp: Date.now()
                };
                that.messages.push(assistantMessage);
				// 模拟一条当先需要回复消息，当消息内容为空时，显示加载中图标
				this.$forceUpdate()

				// 回复消息归0，从第一条开始，现实流式响应也是一段一段的收到消息并且进行响应
				this.imitateIndex = 0;
                this.toSend(msg);
			},
			// h5回复消息
			//#ifdef H5
			toSend(msg) {
				const self = this;
                // 原始API URL
                const targetUrl = self.baseUrl+'/api/'+self.SendingType;
                const url =self.requesttype==2? self.proxyUrl+''+ targetUrl:targetUrl;
                var data;
                if (self.SendingType === 'chat') {
        		//	if (typeof fullText === 'string' && fullText.trim().length > 0) {
        		//		msg = `基于以下上下文：\n${fullText}\n\n请回答：${msg}`;
        				//console.log(input);
        		//	}
        			data = {
        				model: self.baseModel,
        				messages: self.messages,
        				stream: true
        			};
        		} else {
        			//if (typeof fullText === 'string' && fullText.trim().length > 0) {
        			//	input = `基于以下上下文：\n${fullText}\n\n请回答：${input}`;
        			//	console.log(input);
        			//}
        			data = {
        				model: baseModel,
        				prompt: msg
        			};
        		}
                console.log(data);
                fetch(url, {
    				method: 'POST',
    				headers: {
    					'Content-Type': 'application/json'
    				},
    				body: JSON.stringify(data),
    				mode: 'cors'
    			})
    			.then(response => {
    				if (!response.ok) throw new Error(`HTTP错误: ${response.status}`);
    				const reader = response.body.getReader();
    				const decoder = new TextDecoder('utf-8');
    				let prevChunk = '';
    				function processChunk({
    					done,
    					value
    				}) {
    					if (done) {
    						// 处理流结束后的剩余数据
    						if (prevChunk) {
    							try {
    								const parsed = JSON.parse(prevChunk);
    								self.appendToOutput(parsed);
    							} catch (e) {
    								self.appendToOutput(`解析错误: ${e.message}`, true);
    							}
    						}
    						return; // 结束递归
    					}
    					const chunk = decoder.decode(value, {
    						stream: true
    					});
    					prevChunk += chunk;
    					const lines = prevChunk.split('\n');
    					prevChunk = lines.pop() || ''; // 保存未完成的行
    					for (const line of lines) {
    						try {
                                self.appendToOutput(line);
                                self.startTyping();
    						} catch (e) {
    							self.appendToOutput(`解析错误: ${e.message}`, true);
                                self.startTyping();
    						}
    					}
    					// 继续读取下一个chunk
    					return reader.read().then(processChunk);
    				}
    				// 开始读取流
    				return reader.read().then(processChunk);
    			})
    			.then(() => {
    				console.log('流式处理完成');
    				/*if (targetId === 'chat') {
    					if (outputDiv.value.trim()) {
    						const content = outputDiv.value.split('AI：');
    						messages.push({
    							role: "assistant",
    							content: content[content.length - 1]
    						});
    						if (messages.length > 21) messages.splice(1, 2);
    					}
    					localStorage.setItem("messages", JSON.stringify(messages));
    				}
    				isSending = null;*/
    			})
    			.catch(error => {
    				/*messages.splice(-1, 1);
    				outputDiv.value += `错误：${error.message}\n`;
    				outputDiv.scrollTop = outputDiv.scrollHeight;
    				isSending = null;*/
                    self.appendToOutput(`错误: ${error.message}`, true);
    			});
                /*const requestTask = await uni.request({
                  url: url,
                  method: 'POST',
                  header: {
                    Accept: 'text/event-stream',
				//	'Content-Type': 'application/json'
                    //,'Authorization': `Bearer ${token}`
                  },
                  responseType: 'arraybuffer',
                  data: JSON.stringify(data),
                  enableChunked: true,
                  success: (res) => {
                    console.log('请求成功：', res)
                  },
                  fail: (err) => {
                    console.error('请求失败：', err)
                    throw err
                  }
                });
            
                requestTask.onChunkReceived(async (res) => {
                  self.messages[self.messages.length - 1].isPending = false
                  const uint8Array = new Uint8Array(res.data);
                  const text = new TextDecoder('utf-8').decode(uint8Array);
                  const lines = text.split('\n')
                  for (const line of lines) {
                      const data = line
                      try {
                        const parsed = self.returnParse(data);console.log(parsed);
                        if (parsed.message && parsed.message.content) {
                          //console.log("chant change")
                          that.currentMassage = parsed;
                          const lastMessage = self.messages[self.messages.length - 1];
                          self.currentContent += parsed.message.content
                          lastMessage.content += parsed.message.content
                        }
                        self.startTyping();
                      } catch (e) {
                        console.error('解析数据失败：', e, '原始数据：', data)
                      }
                  }
                });
              } catch (error) {
                console.error('发送消息失败：', error)
                //const lastMessage = self.messages[self.messages.length - 1]
                self.currentContent = '抱歉，发生了错误，请稍后重试。'
                self.startTyping();
              }*/
			},
            //#endif
			// APP回复消息
            //#ifdef APP-PLUS || APP-NVUE
			async toSend(msg) {
				const self = this;
                try {
                // 原始API URL
                const targetUrl = self.baseUrl+'/api/'+self.SendingType;
                const url =self.requesttype==2? self.proxyUrl+''+ targetUrl:targetUrl;
                var data;
                if (self.SendingType === 'chat') {
        		//	if (typeof fullText === 'string' && fullText.trim().length > 0) {
        		//		msg = `基于以下上下文：\n${fullText}\n\n请回答：${msg}`;
        				//console.log(input);
        		//	}
        			data = {
        				model: self.baseModel,
        				messages: self.messages,
        				stream: true
        			};
        		} else {
        			//if (typeof fullText === 'string' && fullText.trim().length > 0) {
        			//	input = `基于以下上下文：\n${fullText}\n\n请回答：${input}`;
        			//	console.log(input);
        			//}
        			data = {
        				model: baseModel,
        				prompt: msg
        			};
        		}
                console.log(data);
                const requestTask = await uni.request({
                  url: url,
                  method: 'POST',
                  header: {
                    Accept: 'text/event-stream',
				//	'Content-Type': 'application/json'
                    //,'Authorization': `Bearer ${token}`
                  },
                  responseType: 'arraybuffer',
                  data: JSON.stringify(data),
                  enableChunked: true,
                  success: (res) => {
                    console.log('请求成功：', res)
                  },
                  fail: (err) => {
                    console.error('请求失败：', err)
                    throw err
                  }
                });
            
                requestTask.onChunkReceived(async (res) => {
                  self.messages[self.messages.length - 1].isPending = false
                  const uint8Array = new Uint8Array(res.data);
                  const text = new TextDecoder('utf-8').decode(uint8Array);
                  const lines = text.split('\n')
                  for (const line of lines) {
                      const data = line
                      try {
                        self.appendToOutput(data);
                        self.startTyping();
                      } catch (e) {
                        console.error('解析数据失败：', e, '原始数据：', data)
                      }
                  }
                });
              } catch (error) {
                console.error('发送消息失败：', error)
                self.appendToOutput('抱歉，发生了错误，请稍后重试。',true);
                self.startTyping();
              }
			},
            //#endif
			// 辅助函数：更新界面并滚动
			appendToOutput(prevChunk, isError = false) {
			    var tep_mesg;
			    if(isError){
			         tep_mesg = prevChunk;
			    }else{
					 const parsed = JSON.parse(prevChunk);
                     tep_mesg = this.SendingType=== 'chat' ? parsed.message.content : parsed.response;
                     this.currentMassage = parsed;
			    }
                if (tep_mesg) {
                  //console.log("chant change")
                  this.currentContent += tep_mesg
                  const lastMessage = this.messages[this.messages.length - 1];
                  lastMessage.content += tep_mesg
                }
			}
		}
	}
</script>

<style lang="scss">

	page {
		background-color: #f3f3f3;
		font-size: 28rpx;
		box-sizing: border-box;
		color: #333;
		letter-spacing: 0;
		word-wrap: break-word;
	}
</style>
